#include "SDL.h"
#include "RtMidi.h"
#include <iostream>
using namespace std;

#if !SDL_VERSION_ATLEAST(1,3,0)
#error "This program cannot run with versions of SDL < 1.3"
#endif

// Platform-dependent sleep routines.
#if defined(__WINDOWS_MM__)
  #include <windows.h>
  #define SLEEP( milliseconds ) Sleep( (DWORD) milliseconds ) 
#else // Unix variants
  #include <unistd.h>
  #define SLEEP( milliseconds ) usleep( (unsigned long) (milliseconds * 1000.0) )
#endif

static RtMidiOut* midiout = NULL;
static vector<unsigned char> MIDI_msg(3);

static void
quit (int rc) {
  if (rc != EXIT_SUCCESS) {
    cerr << "Aborted with error code: " << rc << endl;
  }
  else {
    cout << "Program quitted normally." << endl;
  }
  midiout->closePort(); // Just in case it's not done in destructor
  delete midiout;
  SDL_Quit();
  exit(rc);
}

static void
event_loop () {
  bool done = false;
  SDL_Event evt;

  while (!done) {
    while (SDL_PollEvent(&evt) > 0) {
      switch (evt.type) {
        case SDL_QUIT:
        {
          done = true;
        }
        break;
        case SDL_FINGERDOWN:
        case SDL_FINGERMOTION:
        {
          SDL_TouchFingerEvent tfe = evt.tfinger;
          /**
            * Let's do it simple for the moment: split the
            * pad in 2 columns and assign a channel for each.
            */
          Uint16 x = tfe.x;
          Uint16 y = tfe.y;
          Uint8 channel = (x < 16000) ? (0) : (1);
          /**
            * The 'y' coordinate gives us the value of the
            * expression to give to the channel, given a little
            * linear transformation [6000,26000]->[0,127].
            */
          // Clip coordinate first
          if (y < 6000) {
            y = 6000;
          }
          else if (y > 26000) {
            y = 26000;
          }
          Uint8 expression = 127 - static_cast<Uint8>(
                              (static_cast<float>(y) - 6000.f) *
                              (127.f / 20000.f));
          cout << "-> Channel " << static_cast<int>(channel) << " expression = "
               << static_cast<int>(expression) << endl;
          
          // Send the appropriate MIDI event
          // Control change on channel: 1011 cccc
          MIDI_msg[0] = 0xb0 | static_cast<unsigned char>(channel);
          // Expression: 0000 1011  (control 11)
          MIDI_msg[1] = 0x07;
          // Value of the expression
          MIDI_msg[2] = static_cast<unsigned char>(expression);
          cout << "---> MIDI Message: " << (int)MIDI_msg[0] << " " << (int)MIDI_msg[1] <<
            " " << (int)MIDI_msg[2] << endl;
          midiout->sendMessage(&MIDI_msg);
        }
        /*
        case SDL_FINGERDOWN:
        {
          SDL_TouchFingerEvent tfinger = evt.tfinger;
          printf("FingerID: %i", tfinger.fingerId);
          cout << "Finger: " << static_cast<int>(tfinger.fingerId)
               << " pressed with pressure: " << tfinger.pressure << endl;
          cout << "Current position is: " << tfinger.x
                << ", " << tfinger.y << endl;
        }
        break;
        case SDL_FINGERUP:
        {
          SDL_TouchFingerEvent tfinger = evt.tfinger;
          cout << "Finger: " << static_cast<int>(tfinger.fingerId)
               << " released" << endl;
        }
        break;
        case SDL_FINGERMOTION:
        {
          SDL_TouchFingerEvent tfinger = evt.tfinger;
          cout << "Finger: " << static_cast<int>(tfinger.fingerId)
               << " moved with vector ("
               << tfinger.dx << ", " << tfinger.dy
               << ") with pressure: " << tfinger.pressure << endl;
          cout << "Current position is: " << tfinger.x
                << ", " << tfinger.y << endl;
        }
        break;*/

      }
    }
  }

}

static void
MIDI_init () {
  try {
    midiout = new RtMidiOut();
  }
  catch (RtError& error) {
    error.printMessage();
    quit(EXIT_FAILURE);
  }
  midiout->openVirtualPort ("VTouchMix_OUT");
}

int
main (int argc, char** argv) {
  if (SDL_Init(SDL_INIT_VIDEO) < 0) {
    cerr << "Cannot initialize SDL." << endl;
    quit(EXIT_FAILURE);
  }
  
  SDL_Surface* screen = NULL;
  screen = SDL_SetVideoMode (1024, 768, 0, SDL_ANYFORMAT);
  if (screen == NULL) {
    cerr << "Cannot setup a 1024x768 anyformat display." << endl;
    quit(EXIT_FAILURE);
  }

  MIDI_init ();
  event_loop ();

  quit(EXIT_SUCCESS);
}

